(*** Init ***)
let debug = new Debug.debug
let _filePath = ref "" (* variable ou on stock le chemin de l'image*)
let _acc = ref 0
let _outputString = ref [""]
let _listBuffer = ref []
let _nbTab = ref 0

let _ = GMain.init () (* initialisation du main *)

(* Fenêtre principale (non redimensionnable). *)
let mainWindow = GWindow.window
  ~width:800
  ~height:600
  ~position:`CENTER
  ~resizable:true
  ~title:"Aurora" ()

  
(*** Menu du haut ***)
(* première box ajouté a la fenetre mainWindow principale *)
let vboxMenu =
  GPack.vbox
    ~spacing:4
    ~border_width:4
    ~packing:mainWindow#add ()
    
let upMenu = GMenu.menu_bar 
  ~packing:vboxMenu#pack ()
  
(*** Barre d'outil ***)
let toolBar = GButton.toolbar
  ~orientation:`HORIZONTAL
  ~style:`BOTH
  ~packing:vboxMenu#pack ()
  
let vboxUnderToolbar =
  GPack.vbox
    ~spacing:4
    ~border_width:4
    ~packing:vboxMenu#add ()
    
let hboxCodeDebug =
   GPack.hbox 
   ~spacing:4
   ~border_width:4
   ~packing:vboxUnderToolbar#add ()

(*** Ajout des onglets ***)

let noteBook = GPack.notebook
  ~homogeneous_tabs:true
  ~show_border:true
  ~show_tabs:true
  ~border_width:4
  ~width:700
  ~height:300
  ~packing:hboxCodeDebug#add () 

let tabText1 = GMisc.label ~text:"Onglet" ()
  
let tab1 =
  GPack.hbox
    ~homogeneous:false
    ~spacing:4
    ~border_width:4 () 
    
let addTab1 = noteBook#insert_page
  ~tab_label:tabText1#coerce tab1#coerce

let scroll = GBin.scrolled_window
    ~hpolicy:`ALWAYS
    ~vpolicy:`ALWAYS
    ~shadow_type:`ETCHED_IN
    ~packing:tab1#add ()

let textCode = GText.view (* le text *)
        ~editable:true
        ~width:700
        ~height:300
        ~packing:scroll#add ()

(* let _ = textCode#misc#modify_font_by_name "Monospace 10"*)        
let _ = textCode#set_wrap_mode `CHAR
let _ = _listBuffer := textCode::(!_listBuffer)

(*** Debogueur ***)
let noteBookDebug = GPack.notebook
  ~homogeneous_tabs:true
  ~show_border:true
  ~show_tabs:true
  ~border_width:4
 (* ~packing:tab2#add () *)
  ~packing:vboxUnderToolbar#add ()

let tabTextDebug = GMisc.label ~text:"Debug" ()
  
let tabDebug =
  GPack.hbox
    ~homogeneous:false
    ~spacing:4
    ~border_width:4 () 
    
let addTabDebug = noteBookDebug#insert_page
  ~tab_label:tabTextDebug#coerce tabDebug#coerce

let scrollDebug = GBin.scrolled_window
    ~hpolicy:`ALWAYS
    ~vpolicy:`ALWAYS
    ~shadow_type:`ETCHED_IN
    ~packing:tabDebug#add ()

let textDebug =
    GText.view
    ~editable:false
    ~packing:scrollDebug#add ()
 
(*** Information ***)
let noteBookInfo = GPack.notebook
  ~homogeneous_tabs:true
  ~show_border:true
  ~show_tabs:true
  ~border_width:4
  ~packing:hboxCodeDebug#add () 

let tabTextInfo = GMisc.label ~text:"Info" ()
   
let tabInfo =
  GPack.hbox
    ~homogeneous:false
    ~spacing:4
    ~border_width:4 ()
    
let addTabInfo = noteBookInfo#insert_page
  ~tab_label:tabTextInfo#coerce tabInfo#coerce
 
let scrollInfo = GBin.scrolled_window
    ~hpolicy:`ALWAYS
    ~vpolicy:`ALWAYS
    ~shadow_type:`ETCHED_IN
    ~packing:tabInfo#add ()

    
let textInfo =
    GText.view
    ~editable:false
    ~packing:scrollInfo#add ()


(*** fonctions utile a la creation de widget  ***)
let fileButton label stock2 action =
  let button = GButton.button
    ~label:label
    ~packing:toolBar#add () in 
    ignore (GMisc.image ~stock:stock2 ~packing:button#set_image ());
    ignore (button#connect#clicked action);
    button
    
exception IsNone
  
let strOp = function
  | Some x -> x
  | _ -> raise IsNone
  
let codeFilter = GFile.filter
  ~name:"Code File"
  ~patterns:["*.ml"; "*.c"]()

let saveText path =
    let code = open_out path in
    output_string code ((List.nth !_listBuffer noteBook#current_page)#buffer#get_text ());
    close_out code

let loadText path = 
  let text = open_in path in
  let lenght = in_channel_length text in
  let str = String.create lenght in
    really_input text str 0 lenght;
    close_in text;
    (List.nth !_listBuffer noteBook#current_page)#buffer#set_text (str)
 
let openBox action stock id fonction =
  let dlg = GWindow.file_chooser_dialog
    ~action:action
    ~parent:mainWindow
    ~position:`CENTER_ON_PARENT
    ~title: "Chargement d'un fichier"
    ~destroy_with_parent:true () in
    dlg#set_filter codeFilter;
    dlg#add_button_stock `CANCEL `CANCEL;
    dlg#add_select_button_stock id stock;
    if dlg#run() = stock 
    then ((_filePath := (strOp(dlg#filename)));
            fonction !_filePath);
            dlg#misc#hide ()

let startDialog dlg = fun () -> dlg#run (); dlg#misc#hide ()  


(*** Fonctions -> Onglet dynamique ***)

let createNewOnglet _ =
    let tabText = GMisc.label ~text:"Onglet" () in  
    let vtab = GPack.vbox (* box qui contient le texte *)
        ~homogeneous:false 
        ~spacing:4
        ~border_width:4 () in
    let _ = noteBook#insert_page
        ~tab_label:tabText#coerce vtab#coerce in
    let scrollTxt = GBin.scrolled_window
        ~hpolicy:`ALWAYS
        ~vpolicy:`ALWAYS
        ~shadow_type:`ETCHED_IN
        ~packing:vtab#add () in
    let textCode = GText.view (* le text *)
        ~editable:true
        ~width:800
        ~height:300
        ~packing:scrollTxt#add () in
    _listBuffer := textCode::(!_listBuffer);
    _nbTab := !_nbTab + 1;
    noteBook#goto_page !_nbTab

let removeCurrentTab _ = 
    noteBook#remove_page (noteBook#current_page);
    _nbTab := !_nbTab - 1    

  (* du code deguelasse pour rentre mes onglet un peu dynamique :D *)
  let menu = GMenu.menu ()
  let menuItem = GMenu.menu_item ~label:"Add new tab" ~packing: menu#append ()
  let aCallbackID =  menuItem#connect#activate 
        ~callback:(fun () -> (createNewOnglet (); flush stdout))
  let menuItem = GMenu.menu_item ~label:"Remove current tab" ~packing: menu#append ()
  let aCallbackID = menuItem#connect#activate 
        ~callback:(fun () -> (removeCurrentTab (); flush stdout))
  let _ = 
      noteBook#event#connect#button_press ~callback:(fun event -> let () =
            if ((GdkEvent.Button.button event) = 3) 
            then (GtkMenu.Menu.popup
                    ~button:3
                    ~time:(GdkEvent.get_time event) (menu#as_menu))
            in
            false)
    (* fin du code degue *)
 
(*** Fonctions -> Compilation ***)
let compiler path =
    _outputString := debug#read_process "make";
    textInfo#buffer#set_text "Compilation en cours...";
    List.iter (fun x -> (textDebug#buffer#set_text ((textDebug#buffer#get_text ())^"\n"^x))) !_outputString;
    textInfo#buffer#set_text ((textInfo#buffer#get_text ())^"\n"^"Compilation terminée")
 
(*** Options de l'interface ***)
let saveOption _ = ()
let quitOption _ = ()

(*let openBoxOption _ =
  let dlg = GWindow.dialog
    ~parent:mainWindow
    ~position:`CENTER_ON_PARENT
    ~title: "Sauvegarder un fichier"
    ~destroy_with_parent:true () in
  let noteBookOption = GPack.notebook
    ~homogeneous_tabs:true
    ~show_border:true
     ~show_tabs:true
    ~border_width:4
    ~packing:dlg#vbox#add () in
  (* page color *)
  let tabTextColor = GMisc.label ~text:"Color" () in
  let tabColor = GPack.hbox
    ~homogeneous:false
    ~spacing:4
    ~border_width:4 () in
  let _ = noteBookOption#insert_page
    ~tab_label:tabTextColor#coerce tabColor#coerce in
  let dlgColor = GWindow.color_selection_dialog
    ~parent:dlg
    ~destroy_with_parent:true
    ~position:`CENTER () in
  ignore(dlgColor#ok_button#connect#clicked (fun () -> textCode#misc#modify_base [`NORMAL,
  `COLOR dlgColor#colorsel#color]));
  if(noteBookOption#current_page = 0) then startDialog dlgColor ();
(*page police *)
  let tabTextFont = GMisc.label ~text:"Police" () in
  let tabFont = GPack.hbox
    ~homogeneous:false
    ~spacing:4
    ~border_width:4 () in
  let _ = noteBookOption#insert_page
    ~tab_label:tabTextFont#coerce tabFont#coerce in
  (* callback *)
     dlg#add_button_stock `CLOSE `CLOSE;
     dlg#add_button_stock `APPLY `APPLY;
     if(dlg#run() = `APPLY) then saveOption ();
     dlg#misc#hide ()
 (* About button with credits, license, website *)
      
*)
let aboutButton _ =
  let dialog = GWindow.about_dialog
    ~authors:
    ["EpiStudio: \n
Theo \"DarK_Phe0niX\" Sellem\n<theo.sellem@epita.fr>\n
Quentin \"Le Gay\" Ribière\n<quentin.ribiere@epita.fr>\n
Johann \"TheJohKill\" Aurieres\n<johann.aurieres@epita.fr>\n
Matthieu \"jerska(scouille)\" Dumont\n<matthieu.dumont@epita.fr>"]
    ~copyright:"Aurora © 2012 By EpiStudio"
    ~license:"LGPLv3"
    ~version:"v0.1" 
    ~website:"http://www.aurora.com"
    ~position:`CENTER_ON_PARENT
    ~parent:mainWindow
    ~destroy_with_parent:true () in
    dialog#set_name "Aurora";
    ignore(dialog#run ());
    dialog#misc#hide ()
      

(* GtkMessageDialog - Court message à l'attention de l'utilisateur. *)
let quit _ =
  let dlg = GWindow.message_dialog
    ~message:"<b><big>Voulez-vous vraiment quitter ?</big>\n\n\
      Attention :\nToutes les modifications seront perdues.</b>\n"
    ~parent:mainWindow
    ~destroy_with_parent:true
    ~use_markup:true
    ~message_type:`QUESTION
    ~position:`CENTER_ON_PARENT
    ~buttons:GWindow.Buttons.yes_no () in
  let res = dlg#run () = `YES in if(res) then (GMain.quit ());dlg#destroy ();
  res
    
(*** configuration de menu en haut ***)
let fileEntries ()=
  [
    `I ("Ouvrir un fichier",  fun _ -> openBox `OPEN `OPEN `OPEN loadText); 
    `I ("Sauvegarder un ficier", fun _ -> openBox `SAVE `SAVE `SAVE saveText);
    `S;
    `I ("Nouvelle onglet",createNewOnglet);
    `S;
    `I ("Quitter", fun () -> ignore(quit()); ());
  ]
    
let editEntries ()=
  [
    `I ("Compiler",compiler);
    
    `I ("Mode pas à pas",  fun () -> ());
  ]
   
let toolEntries ()=
  [
    `I ("A venir", fun () -> ());   
  ]

let infoEntries ()=
  [
    `I ("A propos",aboutButton);
  ]
    
let optionList = GMenu.menu_item
  ~label:"Fichier"
  ~packing:upMenu#append
  ()
  
let optionEdit = GMenu.menu_item
  ~label:"Edition"
  ~packing:upMenu#append
  ()
  
let optionTool = GMenu.menu_item
  ~label:"Outils"
  ~packing:upMenu#append
  ()
  
let optionInfo = GMenu.menu_item
  ~label:"?"
  ~packing:upMenu#append
  ()
  
let menuOption = GMenu.menu ~packing:optionList#set_submenu ()
let menuEdit = GMenu.menu ~packing:optionEdit#set_submenu ()
let menuTool = GMenu.menu ~packing:optionTool#set_submenu ()
let menuInfo = GMenu.menu ~packing:optionInfo#set_submenu ()
  
let toolbox = GToolbox.build_menu
  menuOption
  ~entries:(fileEntries ())
  
  
let toolbox = GToolbox.build_menu
  menuEdit
  ~entries:(editEntries ())
  
let toolbox = GToolbox.build_menu
  menuTool
  ~entries:(toolEntries ())
  
let toolbox = GToolbox.build_menu
  menuInfo
  ~entries:(infoEntries ())
  
  
(*** Button Open, About & Quit, Afficher un texte à l'écran ***)
      
let openButton = fileButton "Ouvrir" `OPEN
    (fun () -> openBox `OPEN `OPEN `OPEN loadText)

let saveButton = fileButton "Sauvegarder" `SAVE
    (fun () -> openBox `SAVE `SAVE `SAVE saveText)
      
let separator = 
  GMisc.separator `VERTICAL
    ~packing:toolBar#add ()

let compilButton = fileButton "Compiler" `MEDIA_PLAY compiler      

let separator2 = 
  GMisc.separator `VERTICAL
    ~packing:toolBar#add ()



(* GtkColorSelectionDialog - Sélection de couleur. *)
let color_picker =
  let dlg = GWindow.color_selection_dialog
    ~parent:mainWindow
    ~destroy_with_parent:true
    ~position:`CENTER_ON_PARENT () in
  ignore(dlg#ok_button#connect#clicked (fun () -> textCode#misc#modify_base [`NORMAL,
  `COLOR dlg#colorsel#color]));
  fileButton "Couleur de fond" `COLOR_PICKER (startDialog dlg)


(* GtkFontSelectionDialog - Sélection de fonte. *)
let font_button =
  let dlg = GWindow.font_selection_dialog
    ~parent:mainWindow
    ~destroy_with_parent:true
    ~position:`CENTER_ON_PARENT () in
  ignore(dlg#ok_button#connect#clicked (fun () -> 
    textCode#misc#modify_font_by_name dlg#selection#font_name));
  fileButton "Police" `SELECT_FONT (startDialog dlg)

let wordList = ref [""]
let listWord _ = 
    let text = textCode#buffer#get_text in
   for i = 0 to (String.length (text ())) - 1 do
      begin
          let word = ref "" in 
          let c = (text ()).[i] in
          if(c <> ' ') then
              word := !word^(Char.escaped c) 
          else (wordList := !wordList@[!word])
      end
   done

let printWord _ = ArbreLex.printAbr (ArbreLex.construit !wordList)


let about_button = fileButton "A propos" `ABOUT aboutButton
let quitButton = fileButton "Quitter" `QUIT (fun () -> ignore(quit ()); ())
let printWordFile = fileButton "Print" `OK printWord
     
let homeText =
  let text = open_in "text/presentation" in
  let lenght = in_channel_length text in
  let str = String.create lenght in
  let _ = really_input text str 0 lenght in
  let _ = close_in text in
    textCode#buffer#set_text (str)
      
    
let _ =
  if Array.length Sys.argv > 1 then
    begin
      if Sys.argv.(1) = "--help" || Sys.argv.(1) = "-help" then 
	begin
	  let text = open_in "text/README" in
	  let length = in_channel_length text in
	  let str = String.create length in
	    really_input text str 0 length;
	    close_in text;
	    print_string str
	end
      else
	Printf.printf
	  ("\n\nTapez --help ou -help pour plus d'informations\n\n")
    end
  else
    begin
      ignore(mainWindow#event#connect#delete quit);
      mainWindow#show ();
      GMain.main ()
    end
